"""
全局异常处理中间件
统一处理所有异常并返回标准化的错误响应
"""

from typing import Callable, Optional
from fastapi import FastAPI, Request, status, HTTPException
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
from starlette.exceptions import HTTPException as StarletteHTTPException
from sqlalchemy.exc import SQLAlchemyError, DatabaseError as SQLDatabaseError, IntegrityError

from src.exceptions import (
    BaseAppException,
    ErrorResponse,
    create_error_response,
    http_exception_handler,
    base_app_exception_handler,
    DatabaseError
)
from src.utils.logging import get_logger

logger = get_logger(__name__)


async def global_exception_handler(request: Request, exc: Exception) -> JSONResponse:
    """
    全局异常处理器
    捕获所有异常并返回标准化的错误响应
    """
    # 记录错误日志
    logger.error(
        f"全局异常捕获: {type(exc).__name__}",
        exc_info=exc,
        extra={
            "path": request.url.path,
            "method": request.method,
            "client": request.client.host if request.client else "unknown"
        }
    )
    
    # 处理不同类型的异常
    if isinstance(exc, BaseAppException):
        return await handle_base_app_exception(request, exc)
    elif isinstance(exc, RequestValidationError):
        return await handle_validation_error(request, exc)
    elif isinstance(exc, (HTTPException, StarletteHTTPException)):
        return await handle_http_exception(request, exc)
    elif isinstance(exc, IntegrityError):
        return await handle_integrity_error(request, exc)
    elif isinstance(exc, SQLDatabaseError):
        return await handle_database_error(request, exc)
    elif isinstance(exc, SQLAlchemyError):
        return await handle_sqlalchemy_error(request, exc)
    else:
        return await handle_unexpected_error(request, exc)


async def handle_base_app_exception(request: Request, exc: BaseAppException) -> JSONResponse:
    """处理基础应用异常"""
    error_response = create_error_response(exc)
    return JSONResponse(
        status_code=exc.status_code,
        content=error_response.model_dump()
    )


async def handle_validation_error(request: Request, exc: Exception) -> JSONResponse:
    """处理请求验证错误"""
    from src.exceptions import ValidationError
    
    # 确保传入的是RequestValidationError
    if not isinstance(exc, RequestValidationError):
        validation_error = ValidationError(message="请求参数验证失败")
    else:
        # 提取第一个错误信息
        if exc.errors():
            first_error = exc.errors()[0]
            field = ".".join(str(loc) for loc in first_error.get("loc", []))
            message = first_error.get("msg", "参数验证失败")
            
            validation_error = ValidationError(
                message=f"请求参数验证失败: {message}",
                field=field
            )
        else:
            # 默认验证错误响应
            validation_error = ValidationError(message="请求参数验证失败")
    
    error_response = create_error_response(validation_error)
    return JSONResponse(
        status_code=status.HTTP_400_BAD_REQUEST,
        content=error_response.model_dump()
    )


async def handle_http_exception(request: Request, exc: Exception) -> JSONResponse:
    """处理HTTP异常"""
    from src.exceptions import BaseAppException
    
    # 确保传入的是HTTPException或StarletteHTTPException
    if not isinstance(exc, (HTTPException, StarletteHTTPException)):
        base_exception = BaseAppException(
            message=str(exc),
            code="HTTP_ERROR",
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
        )
    else:
        base_exception = BaseAppException(
            message=exc.detail,
            code="HTTP_ERROR",
            status_code=exc.status_code
        )
    
    error_response = create_error_response(base_exception)
    return JSONResponse(
        status_code=base_exception.status_code,
        content=error_response.model_dump()
    )


async def handle_unexpected_error(request: Request, exc: Exception) -> JSONResponse:
    """处理未预期的异常"""
    from src.exceptions import BaseAppException
    
    # 生产环境下隐藏详细错误信息
    error_message = "服务器内部错误"
    
    base_exception = BaseAppException(
        message=error_message,
        code="INTERNAL_SERVER_ERROR",
        status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
    )
    
    error_response = create_error_response(base_exception)
    return JSONResponse(
        status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
        content=error_response.model_dump()
    )


async def handle_integrity_error(request: Request, exc: Exception) -> JSONResponse:
    """处理数据库完整性错误"""
    from src.exceptions import DatabaseError
    
    logger.error(f"数据库完整性错误: {exc}", exc_info=True)
    database_error = DatabaseError(
        message="数据库操作违反完整性约束",
        operation="database_integrity"
    )
    error_response = create_error_response(database_error)
    return JSONResponse(
        status_code=status.HTTP_400_BAD_REQUEST,
        content=error_response.model_dump()
    )


async def handle_database_error(request: Request, exc: Exception) -> JSONResponse:
    """处理数据库错误"""
    from src.exceptions import DatabaseError
    
    logger.error(f"数据库错误: {exc}", exc_info=True)
    database_error = DatabaseError(
        message="数据库连接或操作错误",
        operation="database_operation"
    )
    error_response = create_error_response(database_error)
    return JSONResponse(
        status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
        content=error_response.model_dump()
    )


async def handle_sqlalchemy_error(request: Request, exc: Exception) -> JSONResponse:
    """处理SQLAlchemy错误"""
    from src.exceptions import DatabaseError
    
    logger.error(f"SQLAlchemy错误: {exc}", exc_info=True)
    database_error = DatabaseError(
        message="数据库操作错误",
        operation="sqlalchemy_operation"
    )
    error_response = create_error_response(database_error)
    return JSONResponse(
        status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
        content=error_response.model_dump()
    )


def setup_global_error_handling(app: FastAPI) -> None:
    """
    设置全局异常处理
    """
    # 注册全局异常处理器
    app.add_exception_handler(Exception, global_exception_handler)
    
    # 注册特定异常处理器
    app.add_exception_handler(BaseAppException, base_app_exception_handler)  
    app.add_exception_handler(HTTPException, http_exception_handler)  
    app.add_exception_handler(StarletteHTTPException, http_exception_handler)  
    app.add_exception_handler(RequestValidationError, handle_validation_error)  
    app.add_exception_handler(SQLAlchemyError, handle_sqlalchemy_error)  
    app.add_exception_handler(SQLDatabaseError, handle_database_error)  
    app.add_exception_handler(IntegrityError, handle_integrity_error)  
    
    logger.info("全局异常处理中间件已设置")


# 快捷函数用于抛出异常
